package com.ldzy.webase.controller;

import com.auth0.jwt.JWT;
import com.ldzy.webase.annotation.PassToken;
import com.ldzy.webase.annotation.UserLoginToken;
import com.ldzy.webase.entity.Comment;
import com.ldzy.webase.entity.Press;
import com.ldzy.webase.entity.User;
import com.ldzy.webase.exception.ExceptionResponse;
import com.ldzy.webase.exception.ExceptionResponseCode;
import com.ldzy.webase.service.UserService;
import com.ldzy.webase.utils.Response;
import com.ldzy.webase.utils.ResponseCode;
import com.ldzy.webase.utils.ResponseToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author ：Lq
 * @version ：1.0
 * @date ：2022/10/23 15:27
 * @description ：t_user-用户表-控制层
 */
@RestController
@ResponseBody
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * @author ：Lq
     * @date ：2022/10/23 10:55
     * @description ：登陆
     */
    @PostMapping("/login")
    @PassToken
    public ResponseToken login(@RequestBody User user) {
//        System.out.println(user);
        // 登陆成功，获取token
        String token = userService.loginByStudentIdOrPhoneNumber(user);
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 更新最后登陆时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTimeStr = sdf.format(new Date());
        userService.editEndLoginTimeByUid(currentTimeStr, uid);

        // 将 token 返回给前端
        return ResponseToken.build(ResponseCode.SUCCESS_LOGIN, token);
    }
    
    /**
     * @author ：Lq
     * @date ：2022/10/23 17:26
     * @description ：注册
     */
    @PostMapping("/register")
    @PassToken
    public Response register(@RequestBody User user) {
        // 注册
        userService.register(user);

        // 返回成功消息
        return Response.build(ResponseCode.SUCCESS_REGISTER);
    }

    /**
     * @author ：Lq
     * @date ：2022/10/23 10:55
     * @description ：根据token获取用户基本信息
     */
    @GetMapping("/getInfo")
    @UserLoginToken
    public Response getUserInfoByToken(HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 根据token中的uid返回user
        User user = userService.getUserInfoByUid(uid);

        // 将 token 返回给前端
        return Response.build(ResponseCode.SUCCESS, user);
    }

    /**
     * @author ：Lq
     * @date ：2022/10/25 12:03
     * @description ：根据token修改用户基本信息
     */
    @PostMapping("/editUserInfo")
    @UserLoginToken
    public Response editUserInfo(@RequestBody User user, HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 将token中的uid存入，便于数据库sql修改
        user.setUid(uid);

        // 修改用户基本信息
        userService.editUserInfoByUid(user);

        // 返回成功消息
        return Response.build(ResponseCode.SUCCESS_EDIT);
    }

    /**
     * @author ：Lq
     * @date ：2022/11/9 14:13
     * @description ：查询用户所有已发布的咨询
     */
    @GetMapping("/publish-press/list")
    @UserLoginToken
    public Response getPressAllByUid(HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 查询用户所有已发布的咨询
        List<Press> pressList = userService.getPressByUid(uid);

        // 返回成功消息
        return Response.build(ResponseCode.SUCCESS, pressList);
    }

    /**
     * @author ：Lq
     * @date ：2022/11/16 17:15
     * @description ：查询用户所有已发表的评论
     */
    @GetMapping("/publish-comment/list")
    @UserLoginToken
    public Response getCommentAllByUid(HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 查询用户所有已发表的评论
        List<Comment> commentList = userService.getCommentByUid(uid);

        // 返回成功消息
        return Response.build(ResponseCode.SUCCESS, commentList);
    }

    /**
     * @author ：Lq
     * @date ：2022/11/9 14:13
     * @description ：根据咨询pressId和用户uid，删除对应的咨询表t_press中的数据，删除对应的评论表，删除对应的咨询点赞表
     */
    @DeleteMapping("/press/detail/{pressId}")
    @UserLoginToken
    public Response delPressByPressIdAndUid(@PathVariable("pressId") Integer pressId, HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 删除
        userService.delPressByPressIdAndUid(pressId, uid);

        // 返回成功消息
        return Response.build(ResponseCode.SUCCESS);
    }

    /**
     * @author ：Lq
     * @date ：2022/11/16 19:00
     * @description ：根据评论commentId和用户uid，删除对应的评论表
     */
    @DeleteMapping("/comment/detail/{commentId}")
    @UserLoginToken
    public Response delCommentByCommentIdAndUid(@PathVariable("commentId") Integer commentId, HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 删除评论
        userService.delCommentByCommentIdAndUid(commentId, uid);

        // 删除成功，返回成功消息
        return Response.build(ResponseCode.SUCCESS);
    }

    /**
     * @author ：Lq
     * @date ：2022/11/13 16:19
     * @description ：根据咨询pressId和用户uid，编辑对应的咨询表t_press中的数据
     */
    @PostMapping("/press/edit")
    @UserLoginToken
    public Response editPressByPressIdAndUid(@RequestBody Press press, HttpServletRequest httpServletRequest) {
        // 从请求头中取出token
        String token = httpServletRequest.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        press.setUid(uid);

        // 编辑
        userService.editPressByPressIdAndUid(press);

        // 返回成功消息
        return Response.build(ResponseCode.SUCCESS);
    }

    /**
     * @author ：Lq
     * @version ：1.0
     * @date ：2022/11/14 16:45
     * @description ：绑定或更改邮箱账号，校验邮箱验证码是否正确
     */
    @GetMapping("/email/binding")
    @UserLoginToken
    public Response editEmailInfo(@RequestParam(value = "email") String email, @RequestParam(value = "verificationCode") String verificationCode, @RequestParam(value = "checkOnly", defaultValue = "N") String checkOnly, HttpServletRequest request) {
        if (email == null || email.equals("") && verificationCode == null || verificationCode.equals("")) {
            // 验证码为空
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_verificationCode); // (401, "验证码错误，请重新获取")
        }

        // 从请求头中取出token
        String token = request.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        // 获取session对象
        HttpSession session = request.getSession();
        // 由于session.getAttribute()获取到的类型是Object，所以这里需要转换成String类型
        String sessionCode = String.valueOf(session.getAttribute(uid + "emailBinding")); // 获取存储在session中的验证码
        String sessionName = String.valueOf(session.getAttribute(uid + "emailBindingName")); // 获取存储在session中的邮箱账号
        // 验证码要和邮箱账户一对一，不能绑定其他邮箱！
        if (verificationCode.equals(sessionCode) && email.equals(sessionName)) {
            // 创建实体类用来存放数据
            User user = new User();
            user.setEmail(email);
            user.setUid(uid);
            // 为N的时候需要修改邮箱
            // 为Y的时候仅校验，不修改
            if (checkOnly.equals("N")) {
                userService.editUserEmailByUid(user); // 根据学生uid修改用户邮箱
            }
            // 返回成功消息
            return Response.build(ResponseCode.SUCCESS);
        } else {
            // 验证码错误
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_verificationCode); // (401, "验证码错误，请重新获取")
        }
    }

    /**
     * @author ：Lq
     * @date ：2022/11/14 19:02
     * @description ：找回密码，校验邮箱验证码是否正确
     */
    @GetMapping("/email/forgetPwd")
    @PassToken
    public Response editPwdByEmailCode(@RequestParam(value = "email") String email, @RequestParam(value = "password") String password, @RequestParam("verificationCode") String verificationCode, HttpServletRequest request) {
        if (email == null || email.equals("") && verificationCode == null || verificationCode.equals("")) {
            // 验证码为空
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_verificationCode); // (401, "验证码错误，请重新获取")
        }

        // 根据邮箱获取用户uid
        int uid = Integer.parseInt(userService.getUidByEmail(email));

        // 获取session对象
        HttpSession session = request.getSession();
        // 由于session.getAttribute()获取到的类型是Object，所以这里需要转换成String类型
        String sessionCode = String.valueOf(session.getAttribute(uid + "forgetPwd")); // 获取存储在session中的验证码
        String sessionName = String.valueOf(session.getAttribute(uid + "forgetPwdName")); // 获取存储在session中的邮箱账号
        // 验证码要和邮箱账户一对一，不能绑定其他邮箱！
        if (verificationCode.equals(sessionCode) && email.equals(sessionName)) {
            // 创建实体类用来存放数据
            User user = new User();
            user.setPassword(password);
            user.setUid(uid);
            userService.editPwdByUid(user); // 修改用户密码
            // 返回成功消息
            return Response.build(ResponseCode.SUCCESS);
        } else {
            // 验证码错误
            throw ExceptionResponse.build(ExceptionResponseCode.ERROR_NOT_verificationCode); // (401, "验证码错误，请重新获取")
        }
    }

    /**
     * @author ：Lq
     * @date ：2022/11/16 12:50
     * @description ：修改密码
     */
    @PostMapping("/resetPwd")
    @UserLoginToken
    public ResponseToken resetPwd(@RequestBody Map<Object, String> map, HttpServletRequest request) {
        // 从请求头中取出token
        String token = request.getHeader("Authorization");
        // 从token中取出的uid，不需要担心是否为null，因为@UserLoginToken注解已经验证过了
        int uid = Integer.parseInt(JWT.decode(token).getAudience().get(0));

        String newPassword = map.get("newPassword"); // 获取新密码
        String oldPassword = map.get("oldPassword"); // 获取旧密码

        // 修改密码并返回新生成的token
        token = userService.editPwdByUidAndOldPassword(uid, newPassword, oldPassword);

        // 将 token 返回给前端
        return ResponseToken.build(ResponseCode.SUCCESS, token);
    }
}
